#include "FractalRect.h"

QPointer<FractalRect> FractalRect::_self = 0L;

FractalRect* FractalRect::self( const int _wi , const int _hi , QObject *_parent)
{
	if ( !_self )
	_self = new FractalRect( _wi,_hi,_parent);
	return _self;
}

FractalRect::FractalRect( const int _wi , const int _hi , QObject *_parent )
	: _size(_wi,_hi),endingloop(false),piece_splitmax(100),par(_parent)
{
    
    qDebug() << "### dimension" << _wi << "x" << _hi;
    piece_splitmax = qBound(200,(int) (_wi  / 9.14) ,8000);
    qDebug() << "### piece_splitmax   " << steeps();
    
    
     for (int y = 0; y < height(); y+=steeps())  {
         bool lastLine = (y + piece_splitmax + 1) > height() == true ? true : false;
         ///////qDebug() << "### line " <<  y << lastLine;
         scanninsertLine(y,lastLine);
     }
     _piece  = chess.size();
     /*
      QMapIterator<int,QRect> i(chess);
        while (i.hasNext()) {
             i.next();
             qDebug() << "### chess " << i.key() << "/" << i.value();
         }
     */
     
    qDebug() << "### size " <<  _piece << "  dimension" << _wi << "x" << _hi;
}


void FractalRect::scanninsertLine( const int y , bool ending )
{
    if (y<0)
        return;
    
        for (int x = 0; x < width(); x+=steeps())  {
            bool lastLine = (x + piece_splitmax + 1) > width() == true ? true : false;
            //////qDebug() << "### cools " <<  x << lastLine;
            const uint _wwi = qBound ((uint)1,width() - x,(uint)piece_splitmax);
            const uint _whi = qBound ((uint)1,height() - y,(uint)piece_splitmax);
            ///////if (!ending && !lastLine) 
              chess.insert(chess.size(),QRect(x,y,_wwi,_whi));
            
            if (lastLine) {
                endingloop = true;
            }
        }

    
}

QRect FractalRect::spin(const int iteration)
{
      const QRect piece = chess[iteration];
     if (!piece.isNull()) {
       return piece;
     } 
     return QRect();
}



void FractalRect::paintImage(  QPainter *p   , const QRect viewpart )
{
    const QTransform matrix = p->worldTransform();
    const qreal actualscaling = matrix.m11();
    const QTransform  inmatrix(actualscaling,0.,0.,actualscaling,0,0);
    const QTransform camai = inmatrix.inverted();
    QRect parasi = QRect(0,0,p->device()->width(),p->device()->height()); /// inmatrix.mapRect(boundingRect());
    parasi.moveTopLeft ( viewpart.topLeft() );
    const QRect realviewBounding = camai.mapRect(parasi);
    
    p->setBrush(QColor("#ffffff"));
    p->setPen(Qt::NoPen);
    p->drawRect(QRect(0,0,width(),height()));
    
    
    /*
     const qreal showline = 8;
    QPainterPath path;
    path.addRect(realviewBounding.adjusted (+showline,+showline,-showline,-showline));
    p->setBrush(QColor(Qt::darkRed));  /////debug view rect !!!
    p->drawPath(path);
    */
    
    
    int equars = 0;
    
     QMapIterator<int,QRect> i(chess);
        while (i.hasNext()) {
             i.next();
             const QRect piece = i.value();
             if ( realviewBounding.contains(piece.topLeft()) || realviewBounding.contains(piece.topRight()) ||
                  realviewBounding.contains(piece.bottomLeft()) || realviewBounding.contains(piece.bottomRight())) {
                equars++;
                paintBorder(p,piece,i.key());
             }
         }
         
    qDebug() << "### FractalRect::paintImage  sign " <<  equars << " from " << chess.size();
         
    ///////p->restore();
}

void FractalRect::paintBorder(  QPainter *painter   ,  const QRect brect , const int pos )
{
    const qreal borders = 2;
    const qreal fixpen = borders / 2;
    QPainterPath bordPath;
    bordPath.addRect(brect.adjusted (+fixpen,+fixpen,-fixpen,-fixpen));
    painter->setPen(QPen(Qt::black,borders,Qt::SolidLine,Qt::FlatCap,Qt::MiterJoin));
    
    if (pos%3) {
    painter->setBrush(Qt::NoBrush);
    } else {
    painter->setBrush(Qt::lightGray); 
    }
    
    
    painter->drawPath ( bordPath );
    
    
    
    
    bool lastitem = steeps() == qMin ( brect.height() , brect.width() ) ? false : true;
    
    if (!lastitem) {
    painter->setPen(QPen(Qt::red,1,Qt::SolidLine,Qt::FlatCap,Qt::MiterJoin));
    painter->drawLine ( Diagonal_0( brect ) );
    ///////painter->drawLine ( Diagonal_1( brect ) );
    
    painter->drawText(brect, Qt::AlignCenter ,QString("%1/%2").arg(pos).arg(brect.left() + brect.width()));
    }

}



QLineF FractalRect::Diagonal_0( const QRect rect )
{
  return QLineF(rect.topLeft(),rect.bottomRight());
}

QLineF FractalRect::Diagonal_1( const QRect rect )
{
  return QLineF(rect.topRight(),rect.bottomLeft());
}






